home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
BARNET
/
UTILITIES
/
BASCAT
/
bascat
/
mdwopt.h
< prev
Wrap
C/C++ Source or Header
|
1996-02-23
|
13KB
|
322 lines
/*
* mdwopt.h
*
* Options parsing, similar to GNU getopt_long
*/
/*----- Notices -----------------------------------------------------------*
*
* This program comes with no warranty, not even of any kind, unless
* someone other than the author offers to provide one. It may be used
* and distributed under the terms of the GNU General Public Licence, in
* the interests of promoting freely available software for Linux.
*/
#ifndef MDWOPT_H
#define MDWOPT_H
/*----- Options handling structures ---------------------------------------*/
/* --- mdwopt_data --- *
*
* Contains all the information needed by the mdwopt routine to do its work.
*/
typedef struct
{
/* --- Public variables --- */
char *arg; /* Arg of current option, or 0 */
int opt; /* Value of current option */
int ind; /* 0 for init, index when done */
int err; /* Set nonzero for error messages */
char *prog; /* Program name (from argv[0]) */
/* --- Private variables --- *
*
* Don't play with these, please.
*/
char *list; /* Current short options pointer */
int next; /* Next argument, unpermuted */
int order; /* Ordering of options, flags */
char *env; /* Where we are in the env var */
char *estart; /* Pointer to env var buffer */
}
mdwopt_data;
/*----- Global variables --------------------------------------------------*/
extern mdwopt_data mdwopt_global; /* The default global data */
/* --- For compatibility with older programs (and prettiness) --- *
*
* The macros here access the global structure defined above. I consider it
* to be perfectly acceptable to use these macros in new code, because it
* looks nicer than playing with mdwopt_global.
*/
#define optarg (mdwopt_global.arg) /* Argument of current option */
#define optopt (mdwopt_global.opt) /* Code of current option */
#define opterr (mdwopt_global.err) /* Zero to report error messages */
#define optind (mdwopt_global.ind) /* Index of first non-option */
#define optprog (mdwopt_global.prog) /* Pointer to program name */
/*----- Type definitions --------------------------------------------------*/
/* --- Long options definition table --- */
struct option
{
const char *name; /* Name of the long option */
int has_arg; /* Does it have an argument? */
int *flag; /* Address of flag variable */
int val; /* Value to store/return */
};
/* --- Old-style names for argument flags in long options table --- */
enum
{
no_argument, /* No argument required */
required_argument, /* User must specify argument */
optional_argument /* Argument is optional */
};
/* --- New style flag names --- */
enum
{
gFlag_argReq=1, /* Required argument */
gFlag_argOpt=2, /* Optional argument */
gFlag_switch=4, /* OR val into flag, don't store */
gFlag_negate=8, /* Allow long option to be negated */
gFlag__last_long_opt_flag=0 /* Dummy value */
};
enum
{
gFlag_noLongs=1, /* Don't read long options */
gFlag_noShorts=2, /* Don't read short options */
gFlag_numbers=4, /* Read numeric options */
gFlag_negation=8, /* Allow `+' for negations */
gFlag_envVar=16, /* Parse options from env var */
gFlag__last_mdwopt_flag=0 /* Dummy value */
};
enum
{
gFlag_negated=256, /* Option flag was negated by user */
gFlag__last_return_flag=0 /* Dummy value */
};
/*----- Main code ---------------------------------------------------------*/
/* --- mdwopt --- *
*
* Arguments: int argc == number of command line arguments
* char * const *argv == pointer to command line arguments
* const char *shortopt == pointer to short options information
* const struct option *longopts == pointer to long opts info
* int *longind == where to store matched longopt
* mdwopt_data *data == persistent state for the parser
* int flags == various useful flags
*
* Returns: Value of option found next, or an error character, or
* EOF for the last thing.
*
* Use:
* Reads options. The routine should be more-or-less compatible
* with standard getopts, although it provides many more
* features even than the standard GNU implementation.
*
* The precise manner of options parsing is determined by
* various flag settings, which are described below. By setting
* flag values appropriately, you can achieve behaviour very
* similar to most other getopt routines.
*
*
* How options parsing appears to users
*
* A command line consists of a number of `words' (which may
* contain spaces, according to various shell quoting
* conventions). A word may be an option, an argument to an
* option, or a non-option. An option begins with a special
* character, usually `-', although `+' is also used sometimes.
* As special exceptions, the word containing only a `-' is
* considered to be a non-option, since it usually represents
* standard input or output as a filename, and the word
* containing a double-dash `--' is used to mark all following
* words as being non-options regardless of their initial
* character.
*
* Traditionally, all words after the first non-option have been
* considered to be non-options automatically, so that options
* must be specified before filenames. However, this
* implementation can extract all the options from the command
* line regardless of their position. This can usually be
* disabled by setting one of the environment variables
* `POSIXLY_CORRECT' or `_POSIX_OPTION_ORDER'.
*
* There are two different styles of options: `short' and
* `long'.
*
* Short options are the sort which Unix has known for ages: an
* option is a single letter, preceded by a `-'. Short options
* can be joined together to save space (and possibly to make
* silly words): e.g., instead of giving options `-x -y', a user
* could write `-xy'. Some short options can have arguments,
* which appear after the option letter, either immediately
* following, or in the next `word' (so an option with an
* argument could be written as `-o foo' or as `-ofoo'). Note
* that options with optional arguments must be written in the
* second style.
*
* When a short option controls a flag setting, it is sometimes
* possible to explicitly turn the flag off, as well as turning
* it on, (usually to override default options). This is
* usually done by using a `+' instead of a `-' to introduce the
* option.
*
* Long options, as popularised by the GNU utilities, are given
* long-ish memorable names, preceded by a double-dash `--'.
* Since their names are more than a single character, long
* options can't be combined in the same way as short options.
* Arguments to long options may be given either in the same
* `word', separated from the option name by an equals sign,
* or in the following `word'.
*
* Long option names can be abbreviated if necessary, as long
* as the abbreviation is unique. This means that options can
* have sensible and memorable names but still not require much
* typing from an experienced user.
*
* Like short options, long options can control flag settings.
* The options to manipulate these settings come in pairs: an
* option of the form `--set-flag' might set the flag, while an
* option of the form `--no-set-flag' might clear it.
*
* It is usual for applications to provide both short and long
* options with identical behaviour. Some applications with
* lots of options may only provide long options (although they
* will often be only two or three characters long). In this
* case, long options can be preceded with a single `-'
* character, and negated by a `+' character.
*
* Finally, some (older) programs accept arguments of the form
* `-<number>', to set some numerical parameter, typically a
* line count of some kind.
*
*
* How programs parse options
*
* An application parses its options by calling mdwopt
* repeatedly. Each time it is called, mdwopt returns a value
* describing the option just read, and stores information about
* the option in a data block. The value -1 is returned when
* there are no more options to be read. The `?' character is
* returned when an error is encountered.
*
* Before starting to parse options, the value data->ind must be
* set to 0 or 1. The value of data->err can also be set, to
* choose whether errors are reported by mdwopt.
*
* The program's `argc' and `argv' arguments are passed to the
* options parser, so that it can read the command line. A
* flags word is also passed, allowing the program fine control
* over parsing. The flags are described above.
*
* Short options are described by a string, which once upon a
* time just contained the permitted option characters. Now the
* options string begins with a collection of flag characters,
* and various flag characters can be put after options
* characters to change their properties.
*
* If the first character of the short options string is `+',
* `-' or `!', the order in which options are read is modified,
* as follows:
*
* `+' forces the POSIX order to be used. As soon as a non-
* option is found, mdwopt returns -1.
*
* `-' makes mdwopt treat non-options as being `special' sorts
* of option. When a non-option word is found, the value 0
* is returned, and the actual text of the word is stored as
* being the option's argument.
*
* `!' forces the default order to be used. The entire command
* line is scanned for options, which are returned in order.
* However, during this process, the options are moved in
* the `argv' array, so that they appear before the non-
* options.
*
* A `:' character may be placed after the ordering flag (or at
* the very beginning if no ordering flag is given) which
* indicates that the character `:', rather than `?', should be
* returned if a missing argument error is detected.
*
* Each option in the string can be followed by a `+' sign,
* indicating that it can be negated, a `:' sign indicating that
* it requires an argument, or a `::' string, indicating an
* optional argument. Both `+' and `:' or `::' may be given,
* although the `+' must come first.
*
* If an option is found, the option character is returned to
* the caller. A pointer to an argument is stored in data->arg,
* or NULL is stored if there was no argument. If a negated
* option was found, the option character is returned ORred with
* gFlag_negated (bit 8 set).
*
* Long options are described in a table. Each entry in the
* table is of type `struct option', and the table is terminated
* by an entry whose `name' field is null. Each option has
* a flags word which, due to historical reasons, is called
* `has_arg'. This describes various properties of the option,
* such as what sort of argument it takes, and whether it can
* be negated.
*
* When mdwopt finds a long option, it looks the name up in the
* table. The index of the matching entry is stored in the
* `longind' variable, passed to mdwopt (unless `longind' is 0):
* a value of -1 indicates that no long option was found. The
* behaviour is then dependent on the values in the table entry.
* If `flag' is nonzero, it points to an integer to be modified
* by mdwopt. Usually the value in the `val' field is simply
* stored in the `flag' variable. If the flag gFlag_switch is
* set, however, the value is combined with the existing value
* of the flags using a bitwise OR. If gFlag_negate is set,
* then the flag bit will be cleared if a matching negated long
* option is found. The value 0 is returned.
*
* If `flag' is zero, the value in `val' is returned by mdwopt,
* possibly with bit 8 set if the option was negated.
*
* Arguments for long options are stored in data->arg, as
* before.
*
* Numeric options, if enabled, cause the value `#' to be
* returned, and the numeric value to be stored in data->opt.
*
* If the flag gFlag_envVar is set on entry, options will be
* extracted from an environment variable whose name is built by
* capitalising all the letters of the program's name. (This
* allows a user to have different default settings for a
* program, by calling it through different symbolic links.)
*/
int mdwopt(int argc,char * const *argv,
const char *shortopt,
const struct option *longopts,int *longind,
mdwopt_data *data,int flags);
/* --- Macros for more commonly used routines --- */
#define getopt(c,v,o) mdwopt(c,v,o,0,0,0,gFlag_noLongs)
#define getopt_long(c,v,o,l,li) mdwopt(c,v,o,l,li,0,0)
#define getopt_long_only(c,v,o,l,li) mdwopt(c,v,o,l,li,0,gFlag_noShorts)
/*----- That's all, folks -------------------------------------------------*/
#endif